package com.example.myapplication.viewgroup;

import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by ymz0427 on 2021/8/9
 */
public class FlowLayout extends ViewGroup {




    public FlowLayout(Context context) {
        super(context);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private final int horizontalSpace = dp2px(20);
    private final int verticalSpace = dp2px(10);

    private final List<List<View>> allLines = new ArrayList<>();
    private final List<Integer> heights = new ArrayList<>();

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        allLines.clear();
        heights.clear();

        int paddingLeft = getPaddingLeft();
        int paddingRight = getPaddingRight();
        int paddingTop = getPaddingTop();
        int paddingBottom = getPaddingBottom();

        int usedWidth = 0;
        int height = 0;

        //父布局对FlowLayout的约束宽高
        int seftWidth = MeasureSpec.getSize(widthMeasureSpec) - paddingLeft - paddingRight;
        int seftHeight = MeasureSpec.getSize(heightMeasureSpec) - paddingTop - paddingBottom;

        //FlowLayout的测量宽高
        int needHeight = 0;
        int needWidth = 0;

        List<View> line = new ArrayList<>();


        int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);

            int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight,
                    child.getLayoutParams().width);
            int childHeightSpec = ViewGroup.getChildMeasureSpec(heightMeasureSpec, paddingTop + paddingBottom,
                    child.getLayoutParams().height);
            child.measure(childWidthSpec, childHeightSpec);


            if (usedWidth + horizontalSpace + child.getMeasuredWidth() > seftWidth) {
                //当前行无法在放下下一个view，则保存当前行的Views集合以及当前行的最大高度，
                heights.add(height + verticalSpace);
                allLines.add(line);
                //所有行的最大宽度
                needWidth = Math.max(needWidth, usedWidth);
                //所有行的高度之和
                needHeight += height + verticalSpace;

                //重置下一行的使用宽度、高度、View集合
                usedWidth = 0;
                height = 0;
                line = new ArrayList<>();
            }
            //获取当前行的最大高度，作为当前行的高度
            height = Math.max(height, child.getMeasuredHeight());
            //记录已经使用的宽度
            usedWidth += child.getMeasuredWidth() + (line.size() == 0 ? 0 : horizontalSpace);
            //保存已经测量及模拟布局的View
            line.add(child);

            //记录最后一行的数据
            if (i == count - 1) {
                heights.add(height + verticalSpace);
                allLines.add(line);
                needWidth = Math.max(needWidth, usedWidth);
                needHeight += height + verticalSpace;
            }
        }

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        //如果mode为MeasureSpec.EXACTLY， 则使用widthMeasureSpec中的size，不然使用测量得到的size， 宽高同理
        int realWidth = widthMode == MeasureSpec.EXACTLY ? seftWidth : needWidth;
        int realHeight = heightMode == MeasureSpec.EXACTLY ? seftHeight : needHeight;

        //保存测量的宽和高
        setMeasuredDimension(realWidth + paddingLeft + paddingRight,
                realHeight + paddingTop + paddingBottom - (allLines.size() > 0 ? verticalSpace : 0));
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int left = getPaddingLeft();
        int top = getPaddingTop();
        for (int i = 0; i < allLines.size(); i++) {
            List<View> line = allLines.get(i);
            for (int j = 0; j < line.size(); j++) {
                View child = line.get(j);
                child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
                left += child.getMeasuredWidth() + horizontalSpace;
            }
            left = getPaddingLeft();
            top += heights.get(i);
        }
    }

    public static int dp2px(int dimen) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimen, Resources.getSystem().getDisplayMetrics());
    }
}
